﻿using ApisixSDK.Common.Profile;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Text.Json;
using System.Text.Json.Serialization;
using SufeiUtil;
using ApisixSDK.Common.Http;
using System.Net;
using ApisixSDK.Common.Excetpion;
using ApisixSDK.Admin.model.response;
using Newtonsoft.Json;

namespace ApisixSDK.Common
{
    public abstract class BaseClient
    {
        public const int HTTP_OK = 200;
        public const int HTTP_NOT_OK = 400;
        public const string SDK_VERSION = "0.1.0";

        private Profile.Profile profile;
        private Credential credential;
        private string endpoint;
        private string sdkVersion;
        private string apiVersion;

        private JsonSerializerSettings jSetting = new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore };
        public BaseClient(Profile.Profile profile)
        {
            this.credential = profile.Credential;
            this.profile = profile;
            this.endpoint = profile.Endpoint;
            this.sdkVersion = BaseClient.SDK_VERSION;
            this.apiVersion = profile.Version;

        }

        public virtual Profile.Profile Profile
        {
            get
            {
                return this.profile;
            }
        }
        protected internal virtual string doRequest(string reqMethod, string path)
        {
            var okRsp = doRequest(reqMethod, path, "");
            string strResp = null;
            try
            {
                strResp = okRsp.Html;
            }
            catch (System.IO.IOException e)
            {
                throw new ApisixSDKExcetion(e.GetType().FullName + "-" + e.Message);
            }

            if ((int)okRsp.StatusCode >= BaseClient.HTTP_NOT_OK)
            {
                throw new ApisixSDKExcetion(strResp, okRsp.StatusCode.ToString());
            }

            return strResp;
        }
        protected internal virtual string doRequest(BaseModel model, string reqMethod, string path)
        {
            string strParam = JsonConvert.SerializeObject(model, Formatting.Indented, jSetting); // JsonSerializer.Serialize(model);
            var okRsp = doRequest(reqMethod, path, strParam);
            string strResp = null;
            try
            {
                strResp = okRsp.Html;
            }
            catch (System.IO.IOException e)
            {
                throw new ApisixSDKExcetion(e.GetType().FullName + "-" + e.Message);
            }

            if ((int)okRsp.StatusCode >= BaseClient.HTTP_NOT_OK || (int)okRsp.StatusCode == 0)
            {
                throw new ApisixSDKExcetion(strResp, okRsp.StatusCode.ToString());
            }

            return strResp;
        }
        private HttpResult doRequest(string reqMethod, string path, string param)
        {
            string contentType = "application/json; charset=utf-8";
            Connection conn = new Connection(this.profile.HttpProfile.ConnTimeout, this.profile.HttpProfile.ReadTimeout, this.profile.HttpProfile.WriteTimeout);
            string url = this.profile.HttpProfile.Protocol + this.endpoint + path;
            WebHeaderCollection headers = new WebHeaderCollection();
            headers.Add("Content-Type", contentType);
            headers.Add("Host", this.endpoint);
            headers.Add("X-API-Version", this.apiVersion);
            headers.Add("X-SDK-RequestClient", this.sdkVersion);

            string token = this.credential.Token();
            if (!string.ReferenceEquals(token, null) && token.Length > 0)
            {
                headers.Add("X-API-KEY", token);
            }

            if (reqMethod.Equals(HttpProfile.REQ_GET))
            {
                return conn.GetRequest(url + "?" + param, headers);
            }
            else if (reqMethod.Equals(HttpProfile.REQ_POST))
            {
                return conn.PostRequest(url, param, headers);
            }
            else if (reqMethod.Equals(HttpProfile.REQ_DELETE))
            {
                return conn.DeleteRequest(url, headers);
            }
            else if (reqMethod.Equals(HttpProfile.REQ_PUT))
            {
                return conn.PutRequest(url, param, headers);
            }
            else
            {
                throw new ApisixSDKExcetion("Method only support (GET, POST, PUT, DELETE)");
            }

        }

        protected internal virtual IList<T> arrangeMulti<T>(IList<Item<T>> list) where T : BaseModel
        {
            Item<T> item;
            T model;
            IList<T> result = new List<T>();

            if (list != null)
            {
                for (int i = 0; i < list.Count; i++)
                {
                    item = list[i];
                    model = item.Value;
                    result.Add(model);
                }
            }

            return result;
        }
    }
}
